import time
import re
import random
from django.core.cache import cache
from django.db import transaction

class OrderNumberGenerator:
    """生产级订单号生成服务"""
    
    # 使用Redis计数器确保集群环境下唯一性
    REDIS_KEY_PREFIX = 'order_counter:'
    
    @classmethod
    def generate(cls, user_id, retry=3):
        """
        生成全局唯一订单号
        格式: ORD{日期}{用户ID末3位}{随机数}{集群计数器}
        
        参数:
            user_id: 用户ID (用于关联订单)
            retry: 重试次数 (解决并发冲突)
        """
        if not user_id:
            raise ValueError("用户ID不能为空")
            
        for _ in range(retry):
            try:
                with transaction.atomic():
                    # 获取当日日期字符串 (如20230615)
                    date_str = time.strftime("%Y%m%d")
                    
                    # 获取Redis分布式计数器 (每日重置)
                    counter_key = f"{cls.REDIS_KEY_PREFIX}{date_str}"
                    
                    # 关键修复：检查键是否存在，不存在则初始化
                    if not cache.has_key(counter_key):
                        # 初始化计数器为0，设置24小时过期
                        cache.set(counter_key, 0, timeout=86400)
                    
                    # 递增计数器（此时键已确保存在）
                    counter = cache.incr(counter_key)
                    
                    # 生成3位随机数（使用更安全的随机数生成）
                    random_num = random.randint(100, 999)
                    
                    # 组装订单号：ORD + 日期 + 用户ID末3位 + 3位随机数 + 4位计数器
                    return f"ORD{date_str}{user_id%1000:03d}{random_num:03d}{counter:04d}"
                    
            except Exception as e:
                if _ == retry - 1:  # 最后一次重试仍失败
                    raise ValueError(f"订单号生成失败: {str(e)}")
                time.sleep(0.1)  # 短暂等待后重试
        raise ValueError("订单号生成重试次数耗尽")

    @classmethod
    def validate(cls, order_number):
        """验证订单号格式有效性"""
        pattern = r'^ORD\d{8}\d{3}\d{3}\d{4}$'
        return bool(re.fullmatch(pattern, order_number))